
package com.lida.study.tess4j;

import com.recognition.software.jdeskew.ImageDeskew;
import lombok.extern.slf4j.Slf4j;
import net.sourceforge.tess4j.ITessAPI.TessPageIteratorLevel;
import net.sourceforge.tess4j.ITesseract;
import net.sourceforge.tess4j.ITesseract.RenderedFormat;
import net.sourceforge.tess4j.Tesseract;
import net.sourceforge.tess4j.Word;
import net.sourceforge.tess4j.util.ImageHelper;
import net.sourceforge.tess4j.util.Utils;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * tess4j 测试类
 * @author lD
 * @date 2019/7/25 0025 上午 10:58
 */
@Slf4j
public class Tess4jTest {

    private static final double MINIMUM_DESKEW_THRESHOLD = 0.05d;
    private static ITesseract instance;

    private static final String DATA_PATH = "D:\\project-lida\\study\\src\\main\\resources";
    private static final String TEST_RESOURCES_DATA_PATH = "D:\\project-lida\\study\\src\\main\\resources\\test-data";
    private static final String TEST_RESOURCES_LANGUAGE_PATH = "D:\\project-lida\\study\\src\\main\\resources\\tessdata";

    static {
        Tess4jTest.instance = new Tesseract();
        Tess4jTest.instance.setDatapath(new File(DATA_PATH).getPath());
    }

    public static void main1(String[] args) throws Exception {
        testGetWords();
    }

    /**
     * Test of doOCR method, of class Tesseract.
     * 根据图片文件进行识别
     * @throws Exception while processing image.
     */
    public static void testDoOcrFile() throws Exception {
        log.debug("doOCR on a jpg image");
        File imageFile = new File(TEST_RESOURCES_DATA_PATH, "7.png");
        //set language
        instance.setDatapath(TEST_RESOURCES_LANGUAGE_PATH);
        instance.setLanguage("chi_sim");
        String result = instance.doOCR(imageFile);
        log.debug(result);
    }

    /**
     * Test of doOCR method, of class Tesseract.
     * 根据图片流进行识别
     * @throws Exception while processing image.
     */
    public static void testDoOcrBufferedImage() throws Exception {
        log.debug("doOCR on a buffered image of a PNG");
        File imageFile = new File(TEST_RESOURCES_DATA_PATH, "1.jpg");
        BufferedImage bi = ImageIO.read(imageFile);

        //set language
        instance.setDatapath(TEST_RESOURCES_LANGUAGE_PATH);
        instance.setLanguage("chi_sim");

        String result = instance.doOCR(bi);
        log.debug(result);
    }

    /**
     * Test of getSegmentedRegions method, of class Tesseract.
     * 得到每一个划分区域的具体坐标
     * @throws Exception
     */
    public static void testGetSegmentedRegions() throws Exception {
        log.debug("getSegmentedRegions at given TessPageIteratorLevel");
        File imageFile = new File(TEST_RESOURCES_DATA_PATH, "ocr.png");
        BufferedImage bi = ImageIO.read(imageFile);
        int level = TessPageIteratorLevel.RIL_SYMBOL;
        log.debug("PageIteratorLevel: " + Utils.getConstantName(level, TessPageIteratorLevel.class));
        List<Rectangle> result = instance.getSegmentedRegions(bi, level);
        for (int i = 0; i < result.size(); i++) {
            Rectangle rect = result.get(i);
            log.debug(String.format("Box[%d]: x=%d, y=%d, w=%d, h=%d", i, rect.x, rect.y, rect.width, rect.height));
        }
    }


    /**
     * Test of doOCR method, of class Tesseract.
     * 根据定义坐标范围进行识别
     * @throws Exception while processing image.
     */
    public static void testDoOcrFileRectangle() throws Exception {
        log.debug("doOCR on a BMP image with bounding rectangle");
        File imageFile = new File(TEST_RESOURCES_DATA_PATH, "ocr.png");
        //设置语言库
        instance.setDatapath(TEST_RESOURCES_LANGUAGE_PATH);
        instance.setLanguage("chi_sim");
        //划定区域
        // x,y是以左上角为原点，width和height是以xy为基础
        Rectangle rect = new Rectangle(84, 21, 15, 13);
        String result = instance.doOCR(imageFile, rect);
        log.debug(result);
    }

    /**
     * Test of createDocuments method, of class Tesseract.
     * 存储结果
     * @throws Exception
     */
    public static void testCreateDocuments() throws Exception {
        log.debug("createDocuments for png");
        File imageFile = new File(TEST_RESOURCES_DATA_PATH, "ocr.png");
        String outputbase = "target/test-classes/docrenderer-2";
        List<RenderedFormat> formats = new ArrayList<RenderedFormat>(Arrays.asList(RenderedFormat.HOCR, RenderedFormat.TEXT));

        //设置语言库
        instance.setDatapath(TEST_RESOURCES_LANGUAGE_PATH);
        instance.setLanguage("chi_sim");

        instance.createDocuments(new String[]{imageFile.getPath()}, new String[]{outputbase}, formats);
    }

    /**
     * Test of getWords method, of class Tesseract.
     * 取词方法
     * @throws Exception
     */
    public static void testGetWords() throws Exception {
        log.debug("getWords");
        File imageFile = new File(TEST_RESOURCES_DATA_PATH, "5-thresh.jpg");

        //设置语言库
        instance.setDatapath(TEST_RESOURCES_LANGUAGE_PATH);
        instance.setLanguage("eng");

        //按照每个字取词
        int pageIteratorLevel = TessPageIteratorLevel.RIL_SYMBOL;
        log.debug("PageIteratorLevel: " + Utils.getConstantName(pageIteratorLevel, TessPageIteratorLevel.class));
        BufferedImage bi = ImageIO.read(imageFile);
        List<Word> result = instance.getWords(bi, pageIteratorLevel);

        //print the complete result
        for (Word word : result) {
            log.debug("x:" + word.getBoundingBox().getX() + ",y:" + word.getBoundingBox().getY());
            log.debug("w:" + word.getBoundingBox().getWidth() + ",h:" + word.getBoundingBox().getHeight());
            log.debug("::::");
            log.debug(word.getText());
        }
    }

    /**
     * Test of Invalid memory access.
     * 处理倾斜
     * @throws Exception while processing image.
     */
    public static void testDoOcrSkewedImage() throws Exception {
        //设置语言库
        instance.setDatapath(TEST_RESOURCES_LANGUAGE_PATH);
        instance.setLanguage("chi_sim");
        log.debug("doOCR on a skewed PNG image");
        File imageFile = new File(TEST_RESOURCES_DATA_PATH, "ocr_skewed.jpg");
        BufferedImage bi = ImageIO.read(imageFile);
        ImageDeskew id = new ImageDeskew(bi);
        // determine skew angle
        double imageSkewAngle = id.getSkewAngle();
        if ((imageSkewAngle > MINIMUM_DESKEW_THRESHOLD || imageSkewAngle < -(MINIMUM_DESKEW_THRESHOLD))) {
            // deskew image
            bi = ImageHelper.rotateImage(bi, -imageSkewAngle);
        }

        String result = instance.doOCR(bi);
        log.debug(result);
    }

}
